其他
腾讯新开源的插件化框架 Shadow,原来是这么玩的
https://juejin.im/user/58d9d015ac502e0058df1f96
零反射
框架自身动态化
https://github.com/Tencent/Shadow
│ ├── sample // 示例代码
│ │ ├── README.md
│ │ ├── maven
│ │ ├── sample-constant // 定义一些常量
│ │ ├── sample-host // 宿主实现
│ │ ├── sample-manager // PluginManager 实现
│ │ └── sample-plugin // 插件的实现
│ ├── sdk // 框架实现代码
│ │ ├── coding // lint
│ │ ├── core
│ │ │ ├── common
│ │ │ ├── gradle-plugin // gradle 插件
│ │ │ ├── load-parameters
│ │ │ ├── loader // 负责加载插件
│ │ │ ├── manager // 装载插件,管理插件
│ │ │ ├── runtime // 插件运行时需要,包括占位 Activity,占位 Provider 等等
│ │ │ ├── transform // Transform 实现,用于替换插件 Activity 父类等等
│ │ │ └── transform-kit
│ │ └── dynamic // 插件自身动态化实现,包括一些接口的抽象
宿主中如何启动插件Activity
插件中如何启动插件Activity
classPool: ClassPool,
useHostContext: () -> Array<String>
) : AbstractTransformManager(ctClassInputMap, classPool) {
override val mTransformList: List<SpecificTransform> = listOf(
ApplicationTransform(),
ActivityTransform(),
ServiceTransform(),
InstrumentationTransform(),
RemoteViewTransform(),
FragmentTransform(ctClassInputMap),
DialogTransform(),
WebViewTransform(),
ContentProviderTransform(),
PackageManagerTransform(),
KeepHostContextTransform(useHostContext())
)
}
mapOf(
"android.app.Application"
to "com.tencent.shadow.core.runtime.ShadowApplication"
,
"android.app.Application\$ActivityLifecycleCallbacks"
to "com.tencent.shadow.core.runtime.ShadowActivityLifecycleCallbacks"
)
)
class ActivityTransform : SimpleRenameTransform(
mapOf(
"android.app.Activity"
to "com.tencent.shadow.core.runtime.ShadowActivity"
)
)
@Override
public void onClick(View v) {
// ...
Intent intent = new Intent(MainActivity.this, PluginLoadActivity.class);
intent.putExtra(Constant.KEY_PLUGIN_PART_KEY, partKey);
intent.putExtra(Constant.KEY_ACTIVITY_CLASSNAME, "com.tencent.shadow.sample.plugin.app.lib.gallery.splash.SplashActivity");
// ...
startActivity(intent);
}
});
public void startPlugin() {
PluginHelper.getInstance().singlePool.execute(new Runnable() {
@Override
public void run() {
HostApplication.getApp().loadPluginManager(PluginHelper.getInstance().pluginManagerFile);
// ...
bundle.putString(Constant.KEY_ACTIVITY_CLASSNAME, getIntent().getStringExtra(Constant.KEY_ACTIVITY_CLASSNAME));
HostApplication.getApp().getPluginManager()
.enter(PluginLoadActivity.this, Constant.FROM_ID_START_ACTIVITY, bundle, new EnterCallback() {
@Override
public void onShowLoadingView(final View view) {
// 设置加载的样式
mHandler.post(new Runnable() {
@Override
public void run() {
mViewGroup.addView(view);
}
});
}
// ...
});
}
});
}
}
public void loadPluginManager(File apk) {
if (mPluginManager == null) {
// 创建 PluginManager
mPluginManager = Shadow.getPluginManager(apk);
}
}
public PluginManager getPluginManager() {
return mPluginManager;
}
}
public class Shadow {
public static PluginManager getPluginManager(File apk){
final FixedPathPmUpdater fixedPathPmUpdater = new FixedPathPmUpdater(apk);
File tempPm = fixedPathPmUpdater.getLatest();
if (tempPm != null) {
// 创建 DynamicPluginManager
return new DynamicPluginManager(fixedPathPmUpdater);
}
return null;
}
}
@Override
public void enter(Context context, long fromId, Bundle bundle, EnterCallback callback) {
// 加载 mManagerImpl 实现,这里涉及到了框架的自身动态化,在后面会讲到,这里只要知道,mManagerImpl 最终是 SamplePluginManager 实例即可
updateManagerImpl(context);
// mManagerImpl 是 SamplePluginManager 实例,调用其实现
mManagerImpl.enter(context, fromId, bundle, callback);
mUpdater.update();
}
}
public void enter(final Context context, long fromId, Bundle bundle, final EnterCallback callback) {
// ...
// 启动 Activity
onStartActivity(context, bundle, callback);
// ...
}
private void onStartActivity(final Context context, Bundle bundle, final EnterCallback callback) {
// ...
final String className = bundle.getString(Constant.KEY_ACTIVITY_CLASSNAME);
// ...
final Bundle extras = bundle.getBundle(Constant.KEY_EXTRAS);
if (callback != null) {
// 创建 loading view
final View view = LayoutInflater.from(mCurrentContext).inflate(R.layout.activity_load_plugin, null);
callback.onShowLoadingView(view);
}
executorService.execute(new Runnable() {
@Override
public void run() {
// ...
// 加载插件
InstalledPlugin installedPlugin = installPlugin(pluginZipPath, null, true);
// 创建插件 Intent
Intent pluginIntent = new Intent();
pluginIntent.setClassName(
context.getPackageName(),
className
);
if (extras != null) {
pluginIntent.replaceExtras(extras);
}
// 启动插件 Activity
startPluginActivity(context, installedPlugin, partKey, pluginIntent);
// ...
}
});
}
}
public void startPluginActivity(Context context, InstalledPlugin installedPlugin, String partKey, Intent pluginIntent) throws RemoteException, TimeoutException, FailedException {
Intent intent = convertActivityIntent(installedPlugin, partKey, pluginIntent);
if (!(context instanceof Activity)) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
}
}
public Intent convertActivityIntent(InstalledPlugin installedPlugin, String partKey, Intent pluginIntent) throws RemoteException, TimeoutException, FailedException {
// 创建 mPluginLoader
loadPlugin(installedPlugin.UUID, partKey);
// 先调用 Application onCreate 方法
mPluginLoader.callApplicationOnCreate(partKey);
// 转化插件 intent 为 代理 Activity intent
return mPluginLoader.convertActivityIntent(pluginIntent);
}
}
fun convertActivityIntent(pluginActivityIntent: Intent): Intent? {
return mPluginLoader.mComponentManager.convertPluginActivityIntent(pluginActivityIntent)
}
}
override fun convertPluginActivityIntent(pluginIntent: Intent): Intent {
return if (pluginIntent.isPluginComponent()) {
pluginIntent.toActivityContainerIntent()
} else {
pluginIntent
}
}
private fun Intent.toActivityContainerIntent(): Intent {
// ...
return toContainerIntent(bundleForPluginLoader)
}
private fun Intent.toContainerIntent(bundleForPluginLoader: Bundle): Intent {
val className = component.className!!
val packageName = packageNameMap[className]!!
component = ComponentName(packageName, className)
val containerComponent = componentMap[component]!!
val businessName = pluginInfoMap[component]!!.businessName
val partKey = pluginInfoMap[component]!!.partKey
val pluginExtras: Bundle? = extras
replaceExtras(null as Bundle?)
val containerIntent = Intent(this)
containerIntent.component = containerComponent
bundleForPluginLoader.putString(CM_CLASS_NAME_KEY, className)
bundleForPluginLoader.putString(CM_PACKAGE_NAME_KEY, packageName)
containerIntent.putExtra(CM_EXTRAS_BUNDLE_KEY, pluginExtras)
containerIntent.putExtra(CM_BUSINESS_NAME_KEY, businessName)
containerIntent.putExtra(CM_PART_KEY, partKey)
containerIntent.putExtra(CM_LOADER_BUNDLE_KEY, bundleForPluginLoader)
containerIntent.putExtra(LOADER_VERSION_KEY, BuildConfig.VERSION_NAME)
containerIntent.putExtra(PROCESS_ID_KEY, DelegateProviderHolder.sCustomPid)
return containerIntent
}
}
// ...
override fun onCreate(savedInstanceState: Bundle?) {
// ...
// 设置 application,resources 等等
mDI.inject(this, partKey)
// 创建插件资源
mMixResources = MixResources(mHostActivityDelegator.superGetResources(), mPluginResources)
// 设置插件主题
mHostActivityDelegator.setTheme(pluginActivityInfo.themeResource)
try {
val aClass = mPluginClassLoader.loadClass(pluginActivityClassName)
// 创建插件 activity
val pluginActivity = PluginActivity::class.java.cast(aClass.newInstance())
// 初始化插件 activity
initPluginActivity(pluginActivity)
mPluginActivity = pluginActivity
//设置插件AndroidManifest.xml 中注册的WindowSoftInputMode
mHostActivityDelegator.window.setSoftInputMode(pluginActivityInfo.activityInfo.softInputMode)
// 获取 savedInstanceState
val pluginSavedInstanceState: Bundle? = savedInstanceState?.getBundle(PLUGIN_OUT_STATE_KEY)
pluginSavedInstanceState?.classLoader = mPluginClassLoader
// 调用插件 activity onCreate
pluginActivity.onCreate(pluginSavedInstanceState)
mPluginActivityCreated = true
} catch (e: Exception) {
throw RuntimeException(e)
}
}
// 获取插件资源
override fun getResources(): Resources {
if (mDependenciesInjected) {
return mMixResources;
} else {
return Resources.getSystem()
}
}
}
public void startActivity(Intent intent) {
final Intent pluginIntent = new Intent(intent);
// ...
final boolean success = mPluginComponentLauncher.startActivity(this, pluginIntent);
// ...
}
}
override fun startActivity(shadowContext: ShadowContext, pluginIntent: Intent): Boolean {
return if (pluginIntent.isPluginComponent()) {
shadowContext.superStartActivity(pluginIntent.toActivityContainerIntent())
true
} else {
false
}
}
}
public class ShadowContext extends SubDirContextThemeWrapper {
public void superStartActivity(Intent intent) {
// 调用系统 startActivity
super.startActivity(intent);
}
}
public ComponentName startService(Intent service) {
if (service.getComponent() == null) {
return super.startService(service);
}
Pair<Boolean, ComponentName> ret = mPluginComponentLauncher.startService(this, service);
if (!ret.first)
return super.startService(service);
return ret.second;
}
}
override fun startService(context: ShadowContext, service: Intent): Pair<Boolean, ComponentName> {
if (service.isPluginComponent()) {
// 插件service intent不需要转换成container service intent,直接使用intent
val component = mPluginServiceManager!!.startPluginService(service)
// ...
}
return Pair(false, service.component)
}
}
fun startPluginService(intent: Intent): ComponentName? {
val componentName = intent.component
// 检查所请求的service是否已经存在
if (!mAliveServicesMap.containsKey(componentName)) {
// 创建 Service 实例并调用 onCreate 方法
val service = createServiceAndCallOnCreate(intent)
mAliveServicesMap[componentName] = service
// 通过startService启动集合
mServiceStartByStartServiceSet.add(componentName)
}
mAliveServicesMap[componentName]?.onStartCommand(intent, 0, getNewStartId())
return componentName
}
private fun createServiceAndCallOnCreate(intent: Intent): ShadowService {
val service = newServiceInstance(intent.component)
service.onCreate()
return service
}
}
<receiver android:name="com.tencent.shadow.sample.plugin.app.lib.usecases.receiver.MyReceiver">
<intent-filter>
<action android:name="com.tencent.test.action" />
</intent-filter>
</receiver>
// SampleComponentManager
public class SampleComponentManager extends ComponentManager {
public List<BroadcastInfo> getBroadcastInfoList(String partKey) {
List<ComponentManager.BroadcastInfo> broadcastInfos = new ArrayList<>();
if (partKey.equals(Constant.PART_KEY_PLUGIN_MAIN_APP)) {
broadcastInfos.add(
new ComponentManager.BroadcastInfo(
"com.tencent.shadow.sample.plugin.app.lib.usecases.receiver.MyReceiver",
new String[]{"com.tencent.test.action"}
)
);
}
return broadcastInfos;
}
}
抽象接口类
在插件中实现工厂类
通过工厂类动态创建接口的实现
void loadPluginLoader(String uuid) throws FailedException {
// ...
PluginLoaderImpl pluginLoader = new LoaderImplLoader().load(installedApk, uuid, getApplicationContext());
// ...
}
}
// 创建 PluginLoaderImpl 的工厂类
private final static String sLoaderFactoryImplClassName
= "com.tencent.shadow.dynamic.loader.impl.LoaderFactoryImpl";
// 动态创建 PluginLoaderImpl
PluginLoaderImpl load(InstalledApk installedApk, String uuid, Context appContext) throws Exception {
// 创建插件 ClassLoader
ApkClassLoader pluginLoaderClassLoader = new ApkClassLoader(
installedApk,
LoaderImplLoader.class.getClassLoader(),
loadWhiteList(installedApk),
1
);
// 获取插件中的 工厂类
LoaderFactory loaderFactory = pluginLoaderClassLoader.getInterface(
LoaderFactory.class,
sLoaderFactoryImplClassName
);
// 调用工厂类方法创建 PluginLoaderImpl 实例
return loaderFactory.buildLoader(uuid, appContext);
}
}